package com.example.boot.annotation;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;

import java.io.IOException;

// 动态序列化器，根据 application.yaml 配置动态获取脱敏规则
public class DynamicDesensitizeSerializer extends JsonSerializer<String> implements ContextualSerializer {
    private DesensitizeType desensitizeType;

    private DesensitizeProperties desensitizeProperties;

    /**
     * 执行脱敏序列化
     * @param value 原始字段值
     * @param gen JSON 生成器
     * @param provider 序列化提供器
     */
    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        // 兜底逻辑：配置或规则为空时返回原始值
        if (desensitizeProperties == null || desensitizeType == null) {
            gen.writeString(value);
            return;
        }
        // 根据规则名称获取脱敏配置
        DesensitizeProperties.Rule rule = desensitizeProperties.getRules().get(desensitizeType.name().toLowerCase());
        if (rule != null) {
            // 使用正则替换实现脱敏
            String maskedValue = value.replaceAll(rule.getPattern(), rule.getTemplate());
            gen.writeString(maskedValue);
        } else {
            // 无匹配规则时返回原始值
            gen.writeString(value);
        }
    }

    /**
     * 创建上下文相关的序列化器实例
     * @param prov 序列化提供器（包含 ObjectMapper 配置）
     * @param property 当前序列化的字段属性
     */
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        // 处理字段属性为空的情况（如 Map 中的值）
        if (property == null) return prov.findNullValueSerializer(null);
        // 从 ObjectMapper 的上下文中获取脱敏配置
        DesensitizeProperties properties = (DesensitizeProperties) prov.getAttribute(DesensitizeProperties.class);
        Desensitize annotation = property.getAnnotation(Desensitize.class);
        // 检查字段是否标记了 @Desensitize 注解，且字段类型为 String
        if (annotation != null && String.class.equals(property.getType().getRawClass())) {
            DynamicDesensitizeSerializer serializer = new DynamicDesensitizeSerializer();
            serializer.desensitizeType = annotation.value(); // 设置脱敏类型
            // 将脱敏配置传递给序列化器实例
            return serializer.withProperties(properties);
        }
        // 默认返回其他类型的序列化器
        return prov.findValueSerializer(property.getType(), property);
    }

    /**
     * 注入脱敏配置到序列化器实例
     */
    public DynamicDesensitizeSerializer withProperties(DesensitizeProperties properties) {
        this.desensitizeProperties = properties;
        return this;
    }
}